/**
 * 二维平面上有很多竖条，第i条的横坐标记作i，竖条占据一定的范围记作[L, U]，是相当于纵坐标。
 * 现在给定Q个询问，每次问：
 * a b u v
 * 问能从点(a, b)走到点(u, v)的最短距离是多少，只能走在竖条的范围之内
 * 
 * 假设始终从左向右走，首先贪心，假设当前点是(x, y)，目标点是(u, v)，当x < u时：
 * 1. 如果当前点能够往右走，直接向右即可
 * 2. 否则
 *     2.1 右边条的下边界大于y，则向上走
 *     2.2 否则向下走
 * 然后维护竖条构成的区间
 * 令[leftbot, lefttop]是穿越本竖条区间最优的纵坐标范围
 * [rightbot, righttop]是对应的出口
 * d是对应的最短距离
 * 对于一个[L, U]的竖条而言，就是 {L, U}{L, U}{1, 1}
 * 对于2个竖条，例如[1, 6]、[2, 3]，数据就是{2, 3}{2, 3}{2, 2}
 * 对于更加复杂的，两条路径可能合二为一，例如三个竖条[1, 3][2, 5][4, 7]，数据应该是{3, 3}{4, 4}{4, 4}
 * 总之，知道了两段竖条的情况，可以在O(1)时间合并，用线段树维护
 * 
 * 查询的时候，首先获取区间内竖条的入口与出口情况，如果起点的纵坐标不在入口范围内，就要先移动到最近的入口。
 * 然后再看出口情况，如果是从边界进去，自然是从对应的边界出来。如果就是从起点进去（起点坐标在入口范围内），那就要找与起点最近的出口坐标。
 * 然后再假设出来点与终点的纵坐标之差即可。
 */
#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;

using llt = long long;
using vi = vector<int>;
using vll = vector<llt>;
using pii = pair<int, int>;
using pll = pair<llt, llt>;

struct SegTree{ // 线段树带延迟

using llt = long long;

struct _t{
    array<int, 2> left;  // 左边的下上口
    array<int, 2> right; // 右边的下上口
    llt d;    // 最短距离
    _t(): left({0, 0}), right({0, 0}), d(0LL){}
    _t(int a, int b): left({a, b}), right({a, b}), d(1LL){}
    bool is0() const {return 0LL == d;}
};

int N;

using value_type = _t;
vector<value_type> data; // 线段树



/// 从下往上计算信息，要变动
value_type _up_(const value_type & ls, const value_type & rs) {
    if(ls.is0()) return rs;
    if(rs.is0()) return ls;

    value_type ans;
    if(ls.right[1] <= rs.left[0]){
        ans.left = {ls.left[1], ls.left[1]};
        ans.right = {rs.right[0], rs.right[0]};
        ans.d = ls.d + rs.d + rs.left[0] - ls.right[1];
    }else if(rs.left[0] <= ls.right[1] and ls.right[1] <= rs.left[1] and ls.right[0] <= rs.left[0] and rs.left[0] <= ls.right[1]){
        ans.left = {max(ls.left[0], rs.left[0]), ls.left[1]};
        ans.right = {rs.right[0], min(rs.right[1], ls.right[1])};
        ans.d = ls.d + rs.d;
    }else if(ls.right[1] <= rs.left[1] and rs.left[0] <= ls.right[0]){
        ans.left = ls.left;
        ans.right = {max(rs.right[0], ls.right[0]), min(rs.right[1], ls.right[1])};
        ans.d = ls.d + rs.d;
    }else if(ls.right[1] >= rs.left[1] and rs.left[0] >= ls.right[0]){
        ans.left = {max(ls.left[0], rs.left[0]), min(ls.left[1], rs.left[1])};
        ans.right = rs.right;
        ans.d = ls.d + rs.d;
    }else if(ls.right[0] <= rs.left[1] and rs.left[1] <= ls.right[1] and rs.left[0] <= ls.right[0] and ls.right[0] <= rs.left[1]){
        ans.left = {ls.left[0], min(ls.left[1], rs.left[1])};
        ans.right = {max(ls.right[0], rs.right[0]), rs.right[1]};
        ans.d = ls.d + rs.d;
    }else if(rs.left[1] <= ls.right[0]){
        ans.left = {ls.left[0], ls.left[0]};
        ans.right = {rs.right[1], rs.right[1]};
        ans.d = ls.d + rs.d + (ls.right[0] - rs.left[1]);
    }else{
        assert(0);
    }
    return ans;
}


/// 初始化，清零，不用动
void init(int n) {
    data.assign((N = n) + 1 << 2, value_zero());
}


/// 这个函数不用动
value_type query(int a, int b){
    return _query(1, 1, N, a, b);
}

/// 这个函数不用动
void build() {
    _build(1, 1, N);
}

/// 几乎不用动
value_type _query(int t, int s, int e, int a, int b) {
    if(a <= s and e <= b) {
        return data[t];
    }

    int mid = (s + e) >> 1;
    value_type ans = value_zero(); // 如果求最值，这里不能用zero
    if(a <= mid) ans = _up_(ans, _query(lson(t), s, mid, a, b));
    if(mid < b) ans = _up_(ans, _query(rson(t), mid + 1, e, a, b));
    return ans;
}


/// 这个函数不用动
void _pushUp(int t) {
    data[t] = _up_(data[lson(t)], data[rson(t)]);
}


/// 几乎不用动
void _build(int t, int s, int e) {
    if(s == e) {
        int bot, top; cin >> bot >> top;
        assert(bot <= top);
        data[t] = value_type(bot, top);
        return; 
    }
    int mid = (s + e) >> 1;
    _build(lson(t), s, mid);
    _build(rson(t), mid + 1, e);
    _pushUp(t);
}



/// 辅助函数，视线段树信息类型而变动
static const value_type & value_zero() {
    static const value_type VALUE0;
    return VALUE0;
}

/// 这两个函数不用变动
static int lson(int x) {return x << 1;}
static int rson(int x) {return lson(x) | 1;}

void _disp(int t, int s, int e) const {
    cout << "Node " << t << ", Son(" << lson(t) << ", " << rson(t) << "), ";
    cout << "Left(" << data[t].left[0] << ", " << data[t].left[1] << "), ";
    cout << "Right(" << data[t].right[0] << ", " << data[t].right[1] << "), ";
    cout << "distance = " << data[t].d << endl;
    if(s == e) return;

    int mid = (s + e) >> 1;
    _disp(lson(t), s, mid);
    _disp(rson(t), mid + 1, e);
    return;
}

void disp()const{
    _disp(1, 1, N);
}


};


SegTree St;
int N;
int Q;

void work(){
    cin >> N;
    St.init(N);
    St.build();

#ifndef ONLINE_JUDGE
    St.disp();
#endif

    cin >> Q;
    for(int q=1;q<=Q;++q){
        int a, b, u, v;
        cin >> a >> b >> u >> v;
        if(a == u){
            cout << abs(b - v) << "\n";
            continue;
        }
        if(a > u) {swap(a, u); swap(b, v);}
        auto tmp = St.query(a, u);
        auto ans = tmp.d;
        if(b > tmp.left[1]){
            ans += b - tmp.left[1];
            ans += abs(tmp.right[1] - v);
        }else if(b < tmp.left[0]){
            ans += tmp.left[0] - b;
            ans += abs(tmp.right[0] - v);
        }else{
            if(b > tmp.right[1]){
                ans += abs(tmp.right[1] - v);
            }else if(b < tmp.right[0]){
                ans += abs(tmp.right[0] - v);
            }else{
                ans += abs(b - v);
            }
        }
        cout << ans - 1 << "\n";
    }
    return;
}


int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);	
    int nofkase = 1;
	// cin >> nofkase;
	while(nofkase--) work();
	return 0;
}